-
-
Notifications
You must be signed in to change notification settings - Fork 6
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement vectors without proxy #779
base: main
Are you sure you want to change the base?
Conversation
af23f7e
to
ca3c797
Compare
This pull request is automatically built and testable in CodeSandbox. To see build info of the built libraries, click here or the icon next to each commit SHA. |
packages/typegpu/src/data/vector.ts
Outdated
} | ||
|
||
if (values.length === options.length) { | ||
if (values.length <= 1 || values.length === options.length) { | ||
return options.make(...values); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Arguably, we could pass the values directly to the constructor of the vector and not check lengths. In case someone generates thousands of vectors, these checks can add up. We could simply rely on typescript to handle this for us and not pay the runtime cost (even if small).
I think having the option to initialize using vec4(vec3(), w)
would be super cool, but I did not find a way to do this without paying the cost of checking args. If someone wants to do this in js, the simplest way would be to vec4(...vec3(), w)
. This would work just fine, we just need to adjust the transpiler to ignore the dots.
Awesome initiative! 👏 |
If it can be autogenerated on build for everyone, that would be even better! Although downsides are code size, and not being able to use the library from node without compile step. (Node has experimental type stripping support) |
To be able to validate if the generation works properly, I'd like to codegen to the file system, and commit. So even if a Node project would like to consume the library from source, it should work okay! |
Oooh I see |
ca3c797
to
892aa9c
Compare
Okay, I verified that the `new Function( I would still attempt to offload this work AOT as a prepublish step, and ship the generated code. For now though, we can continue experimenting and pushing the performance with a JIT approach here, as it's easier to prototype with. |
Alright, I think if we're able to support both the slow path (proxy) and the fast path (JIT functions), then we're going to have the best of both worlds. We can go back to generating these functions AOT if we find that that's the better approach. @deluksic Would you be willing to update this PR with a check to see if let EVAL_ALLOWED_IN_ENV: boolean;
try {
new Function(`return true`);
EVAL_ALLOWED_IN_ENV = true;
} catch {
EVAL_ALLOWED_IN_ENV = false;
}
// ... |
I'm looking at this and it is not super easy to switch this at runtime (not impossible). Are you sure we absolutely must support the proxy way? Do you know when |
OK, I found this https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy/script-src#unsafe_eval_expressions I will try to find a way to switch at runtime, hopefully by doing this check only once. It kinda defeats the purpose if every vec creation or access needs to check for |
daa1d2e
to
98340f3
Compare
I lied, I implemented the AOT version instead. It was actually easier. For now I created a |
dbe2cbf
to
3927bc2
Compare
import type { VecKind } from './wgslTypes'; | ||
|
||
export abstract class VecBase extends Array implements SelfResolvable { | ||
abstract get kind(): VecKind; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
switched kind
to a getter, so we don't add a string to each instance of the vector.
get wwwx() { return new this._Vec4(this[3], this[3], this[3], this[0]); } | ||
get wwwy() { return new this._Vec4(this[3], this[3], this[3], this[1]); } | ||
get wwwz() { return new this._Vec4(this[3], this[3], this[3], this[2]); } | ||
get wwww() { return new this._Vec4(this[3], this[3], this[3], this[3]); } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I expect this to compress pretty well, but we should check.
3927bc2
to
6897d1f
Compare
I have an idea for how to reduce the amount of code. What if we add the 4-way swizzle directly on the Added it as an extra commit, we can revert if you don't like this approach. |
Instead of using
Proxy
to implement swizzling, we can usenew Function
to compile small getters with no runtime if / switch. This should allow js engines to optimize these calls better, but more testing is needed. The most important thing is thatvec[0]
andvec.x
are simple index access and a getter respectively.Example swizzle getter:
One important change is the ability to unpack vectors like:
I achieve this by extending
Array
. Typescript doesn't understand yet that this is possible, but I think we should be able to tell it.My first tests show almost 2x speedup in
buffer.write
speed, 25ms vs 40ms for 50kCircle(position, radius, styleIndex)
structs.